import personImg from "@/assets/person.png";
import { Marker, MarkerStyle } from "@/plugins/cesium/index.js";
import IconStyle from "@/plugins/cesium/style/IconStyle.js";
import TextStyle from "@/plugins/cesium/style/TextStyle.js";

let timer = null;
export function formatDate(date, format = "YYYY-MM-DD HH:mm:ss") {
  const year = date.getFullYear();
  const month =
    date.getMonth() + 1 < 10
      ? "0" + (date.getMonth() + 1)
      : date.getMonth() + 1;
  const day = date.getDate() < 10 ? "0" + date.getDate() : date.getDate();
  const hours = date.getHours() < 10 ? "0" + date.getHours() : date.getHours();
  const minutes =
    date.getMinutes() < 10 ? "0" + date.getMinutes() : date.getMinutes();
  const seconds =
    date.getSeconds() < 10 ? "0" + date.getSeconds() : date.getSeconds();
  let formatLabel =
    year +
    "-" +
    month +
    "-" +
    day +
    " " +
    hours +
    ":" +
    minutes +
    ":" +
    seconds;
  switch (format) {
    case "YYYY-MM-DD":
      formatLabel = year + "-" + month + "-" + day;
      break;
    case "HH:mm:ss":
      formatLabel = hours + ":" + minutes + ":" + seconds;
      break;
    default:
      break;
  }
  return formatLabel;
}

// 第一个参数是需要进行防抖处理的函数，第二个参数是延迟时间，默认为1秒钟
// 这里多传一个参数，immediate用来决定是否要第一次立即执行, 默认为false
export function debounce(func, wait = 1000, immediate = false) {
  let timeout;
  return function (...args) {
    let context = this;

    if (timeout) clearTimeout(timeout); // timeout 不为null
    if (immediate) {
      let callNow = !timeout; // 第一次会立即执行，以后只有事件执行后才会再次触发
      timeout = setTimeout(function () {
        timeout = null;
      }, wait);
      if (callNow) {
        func.apply(context, args);
      }
    } else {
      timeout = setTimeout(function () {
        func.apply(context, args);
      }, wait);
    }
  };
}

/**
 * 手写节流
 * @param fn 回调函数
 * @param delay 节流延迟时间 ms
 * @returns {(function(...[*]): void)|*}
 */
export function useThrottled(fn, delay = 500) {
  let timer = null;
  return function (...args) {
    if (!timer) {
      timer = setTimeout(() => {
        fn.apply(this, args);
        timer = null;
      }, delay);
    }
  };
}

export function initBillBordByEntity(kyViewer, num = 100000, position) {
  timer && clearInterval(timer);
  const { lng, lat, height = 2, isMove = false } = position;
  for (let i = 0; i < num; i++) {
    new Marker({
      viewer: kyViewer,
      id: i,
      longitude: lng + (Math.random() - 0.5) * 0.01,
      latitude: lat + (Math.random() - 0.5) * 0.01,
      height,
      style: new MarkerStyle({
        iconStyle: new IconStyle({
          url: personImg,
        }),
        textStyle: new TextStyle({
          text: "阮景涛",
          fillColor: Cesium.Color.fromCssColorString("#c8f5ff"), // 字体填充颜色
          backgroundColor:
            Cesium.Color.fromCssColorString("#072942").withAlpha(0.6),
        }),
      }),
    });
  }
  if (!isMove) return;
  timer = setInterval(() => {
    kyViewer.entities._entities._array.forEach((point) => {
      const carto = Cesium.Cartographic.fromCartesian(point.position._value);
      carto.longitude -= 0.00000001;
      carto.latitude -= 0.00000001;
      point.position = Cesium.Cartographic.toCartesian(carto);
    });
  }, 30);
}

/**
 * 初始化基于Primitive的广告牌（Billboard）集合，用于在Cesium场景中批量添加大量广告牌和标签。
 * 该方法通过PrimitiveCollection优化渲染性能，适用于需要展示大量标记点的场景。
 *
 * @param {Object} kyViewer - Cesium Viewer实例，用于访问场景和渲染器
 * @param {number} [num=100000] - 要创建的广告牌和标签的数量，默认为100000
 * @param {Object} position - 初始位置配置对象
 * @param {number} position.lng - 经度
 * @param {number} position.lat - 纬度
 * @param {number} [position.height=2] - 高度，默认为2米
 * @param {boolean} [position.isMove=false] - 是否启用标记点移动动画，默认为false
 */
export function initBillBordByPrimitive(kyViewer, num = 100000, position) {
  const { lng, lat, height = 2, isMove = false } = position;
  console.log("pos", position, height);
  timer && clearInterval(timer);
  // 创建主Primitive集合，启用顶点缓存优化以提升渲染性能
  const collection = new Cesium.PrimitiveCollection({
    interleave: true,
    vertexCacheOptimize: true,
    // asynchronous : false,
    cull: false,
  });

  // 创建临时Primitive集合（当前未使用）
  const tmepPrimitives = new Cesium.PrimitiveCollection();

  // 创建广告牌集合，设置混合选项为不透明
  const billborardsPrimitives = new Cesium.BillboardCollection({
    blendOption: Cesium.BlendOption.OPAQUE,
  });

  // 创建标签集合，设置混合选项为不透明
  const labelsPrimitives = new Cesium.LabelCollection({
    blendOption: Cesium.BlendOption.OPAQUE,
  });

  // 批量创建广告牌和对应的标签
  for (let i = 0; i < num; i++) {
    // 在初始位置附近随机生成坐标点
    const pos = Cesium.Cartesian3.fromDegrees(
      lng + (Math.random() - 0.5) * 0.01,
      lat + (Math.random() - 0.5) * 0.01,
      height,
    );

    // 添加广告牌到集合中
    const temp = billborardsPrimitives.add({
      position: pos,
      image: personImg,
      height: 30,
      width: 30,
      scaleByDistance: new Cesium.NearFarScalar(2000, 1.0, 2e4, 0),
    });

    // 添加标签到集合中
    const temp2 = labelsPrimitives.add({
      position: pos,
      text: "阮景涛",
      pixelOffset: new Cesium.Cartesian2(0, -40),
      scaleByDistance: new Cesium.NearFarScalar(2000, 1.0, 1e4, 0),
      font: "15px Microsoft Yahei",
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      showBackground: true,
      fillColor: Cesium.Color.fromCssColorString("#c8f5ff"), // 字体填充颜色
      backgroundColor:
        Cesium.Color.fromCssColorString("#072942").withAlpha(0.6),
    });
  }

  // 将广告牌和标签集合添加到主集合中
  collection.add(billborardsPrimitives);
  collection.add(labelsPrimitives);

  // 将主集合添加到场景的Primitive集合中进行渲染
  kyViewer.scene.primitives.add(collection);

  // console.log("collection", collection, billborardsPrimitives, tmepPrimitives);

  // 如果不需要移动效果则直接返回
  if (!isMove) return;

  // 启动定时器实现标记点缓慢移动效果
  timer = setInterval(() => {
    for (let i = 0; i < num; i++) {
      // 获取当前广告牌和标签
      const billboard = billborardsPrimitives.get(i);
      const label = labelsPrimitives.get(i);

      // 获取当前位置并转换为地理坐标
      const carto = billboard
        ? Cesium.Cartographic.fromCartesian(billboard.position)
        : Cesium.Cartographic.fromCartesian(label.position);

      // 更新经纬度实现移动效果
      carto.longitude -= 0.00000001;
      carto.latitude -= 0.00000001;

      // 将更新后的地理坐标转换回笛卡尔坐标并设置给广告牌和标签
      billboard &&
        (billboard.position = Cesium.Cartographic.toCartesian(carto));
      label && (label.position = Cesium.Cartographic.toCartesian(carto));
    }
  }, 30);
}

export function initPointByEntity(kyViewer, num = 100000) {
  for (let i = 0; i < num; i++) {
    kyViewer.entities.add({
      position: Cesium.Cartesian3.fromDegrees(
        111.2 + (Math.random() - 0.5) * 0.03,
        30.68 + (Math.random() - 0.5) * 0.03,
        2,
      ),
      point: {
        color: Cesium.Color.YELLOW,
        outlineColor: Cesium.Color.RED,
        outlineWidth: 2,
        pixelSize: 5,
        // scaleByDistance: new Cesium.NearFarScalar ( 1500 , 1 , 20000 , 0 ),
        disableDepthTestDistance: 2000,
      },
    });
  }
  console.log("所有entity集合", kyViewer.entities);
  setInterval(() => {
    const positionScratch = new Cesium.Cartesian3();
    kyViewer.entities._entities._array.forEach((point) => {
      Cesium.Cartesian3.clone(point.position._value, positionScratch);
      Cesium.Cartesian3.add(
        positionScratch,
        new Cesium.Cartesian3(Math.random(), Math.random() - 0.5, 0),
        positionScratch,
      );
      // console.log(positionScratch)
      point.position = positionScratch;
    });
  }, 100);
}

export function initPointByPrimitive(kyViewer, num = 100000) {
  const pointsPrimitives = kyViewer.scene.primitives.add(
    new Cesium.PointPrimitiveCollection(),
  );
  for (let i = 0; i < num; i++) {
    pointsPrimitives.add({
      position: Cesium.Cartesian3.fromDegrees(
        111.2 + (Math.random() - 0.5) * 0.03,
        30.68 + (Math.random() - 0.5) * 0.03,
        2,
      ),
      color: Cesium.Color.YELLOW,
      outlineColor: Cesium.Color.RED,
      outlineWidth: 2,
      pixelSize: 5,
      disableDepthTestDistance: 2000,
    });
  }
  setInterval(() => {
    const positionScratch = new Cesium.Cartesian3();
    for (let i = 0; i < num; i++) {
      const point = pointsPrimitives._pointPrimitives[i];
      Cesium.Cartesian3.clone(point.position, positionScratch);
      Cesium.Cartesian3.add(
        positionScratch,
        new Cesium.Cartesian3(Math.random(), Math.random() - 0.5, 0),
        positionScratch,
      );
      // console.log('primitive', positionScratch)
      point.position = positionScratch;
    }
  }, 100);
}

/**
 * 保存当前ceisum场景截图
 * @param scene  Cesium.viewer.scene
 */
export function saveCesiumSceneToFile(scene, download = true) {
  scene.render();
  const canvas = scene.canvas;
  // base64字符串
  const image = canvas
    .toDataURL("image/png")
    .replace("image/png", "image/octet-stream");
  if (download) {
    const link = document.createElement("a");
    const blob = dataURLtoBlob(image);
    const objurl = URL.createObjectURL(blob);
    link.download = "pic.png";
    link.href = objurl;
    link.click();
  } else {
    return image;
  }
}

export function dataURLtoBlob(dataurl) {
  let arr = dataurl.split(","),
    mime = arr[0].match(/:(.*?);/)[1],
    bstr = atob(arr[1]),
    n = bstr.length,
    u8arr = new Uint8Array(n);
  // console.log('arr',arr,'bstr',bstr)
  while (n--) {
    u8arr[n] = bstr.charCodeAt(n);
  }
  return new Blob([u8arr], { type: mime });
}

export function sum(...args) {
  return args.reduce((p, c) => p + c, 0);
}
